#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>

#include "Linux_Config.h"
#include "TSS.h"

/**
  * @brief  Linux下开启定时器模拟systick
  * @retval 无
  * @note   无
  */
struct timeval tvstart;
void Systick_Init(void)
{
    timer_t timerid;
    struct sigevent sev = {0};
    sev.sigev_notify = SIGEV_THREAD;
    sev.sigev_signo = SIGRTMIN;
    sev.sigev_notify_function = (void (*)(union sigval))TSS_SystickHandler;
    sev.sigev_notify_attributes = NULL;

    if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1)
    {
        Log_printf("ERROR", "fail to timer_create");
    }

    struct itimerspec its = {0};
    uint32_t tick = 100000.0f / TSS_SYSHZ / 1.556f;
    uint32_t sec = tick / 100000;
    uint32_t nsec = (tick % 100000) * 10000;

    its.it_value.tv_sec = sec;
    its.it_value.tv_nsec = nsec;
    its.it_interval.tv_sec = sec;
    its.it_interval.tv_nsec = nsec;

    if (timer_settime(timerid, 0, &its, NULL) == -1)
    {
        Log_printf("ERROR", "fail to timer_settime");
    }

    gettimeofday(&tvstart, NULL);
}

/**
  * @brief  Linux下模拟串口接收
  * @retval 无
  * @note   从getchar获取字符串
  */
#define BUFFER_MAX 512
static uint16_t RxBufferLen = 0;
static uint8_t RxBuffer[BUFFER_MAX];
//串口接收数据任务
uint8_t USART_RX_TASK_ID = 0;
void Usart_Rx_Task(TSS_TaskMessageDef *p)
{
    Log_printf("Usart", "(%d)%s", RxBufferLen, RxBuffer);
    int8_t ret = TSS_CommandProcess(RxBuffer, RxBufferLen);
    if (ret == TSS_NONEAT)
    {
        Log_printf("AT", "At without this command!\r\n");
    }
    else if (ret == TSS_ATERROR)
    {
        Log_printf("AT", "At command error!\r\n");
    }
    memset(RxBuffer, 0, BUFFER_MAX);
    RxBufferLen = 0;
}
//串口中断服务函数
void *usart_thread_function(void *arg)
{
    while (1)
    {
        /* Read one byte from the receive data register */
        RxBuffer[RxBufferLen] = getchar();
        if (RxBufferLen < BUFFER_MAX)
            RxBufferLen++;
        //延时触发接收任务
        TSS_ThreadSetTrigger(USART_RX_TASK_ID, 5);
    }
    return NULL;
}
void Usart_Init(void)
{
    pthread_t thread;
    pthread_create(&thread, NULL, usart_thread_function, NULL);
    USART_RX_TASK_ID = TSS_ThreadCreate(Usart_Rx_Task, 1, TASK_TRIGGER, 10);
}

/**
  * @brief  Linux下获取时间戳
  * @retval 无
  * @note   无
  */
uint32_t getmstime(void)
{
    uint32_t tm;
    struct timeval tvcurr;
    struct timeval tvdiff;
    gettimeofday(&tvcurr, NULL);
    timersub(&tvcurr, &tvstart, &tvdiff);
    tm = (unsigned int)tvdiff.tv_usec / 1000 + tvdiff.tv_sec * 1000;
    srand(tm);
    return tm;
}

/**
  * @brief  输出log
  * @retval 无
  * @note   无
  */
#define LOGLEN_MAX 1024
char LogBuffer[LOGLEN_MAX] = {0};
void Log_printf(char *head, const char *format, ...)
{
    memset(LogBuffer, 0, LOGLEN_MAX);
    if (head != NULL)
    {
        // sprintf(LogBuffer, "%10u : [%6s] ", getmstime(), head);
        sprintf(LogBuffer, "%10u : [%6s] ", TSS_GetRunTime(), head);
    }

    va_list args;
    va_start(args, format);
    vsprintf(&LogBuffer[strlen(LogBuffer)], format, args);
    va_end(args);

    printf("%s", LogBuffer);
}

/**
  * @brief  将二进制数组转化为ascii字符串
  * @retval Data  待转化的数据区
  * @retval Len   待转化的数据区大小
  * @retval Str   输出数据区
  * @note   需提供一个足够大的Str来存储字符串
  */
void Hex2Ascii(uint8_t *Data, uint16_t Len, uint8_t *Str)
{
    // sprintf((char *)Str, "0x");
    Str[0] = 0;
    for (uint16_t i = 0; i < Len; i++)
    {
        sprintf((char *)&Str[strlen((char *)Str)], "%2X ", Data[i]);
    }
}
